package top.fwpsl.redis;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import top.fwpsl.config.RedisConfig;
import top.fwpsl.util.DateUtil;
import top.fwpsl.util.LogHelper;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 *
 *
 * @auther: 风戏fw
 * @date: 2020/11/21
 */
public abstract class AbstractJedisClient implements IJedisKeyClient, IJedisStringClient,
        IJedisHashClient, IJedisListClient, IJedisSetClient, IJedistZsetClient, IJedisScriptClient{


    protected String geneErrorMessage(String methodName, String key, Object o) {
        return geneErrorMessage(methodName, key, null, o);
    }

    protected String geneErrorMessage(String methodName, String key, String value, Object o) {
        StringBuilder sb = new StringBuilder();
        sb.append("redis template exception:");
        sb.append("methodName=").append(methodName);
        sb.append(",key=").append(key);
        if (value != null) {
            sb.append(",value=").append(value);
        }
        sb.append(",object.class=").append(getObjectClass(o));
        return sb.toString();
    }

    private String getObjectClass(Object o) {
        if (o == null) {
            return "NullClass";
        } else if (o instanceof Class) {
            Class<?> clazz = (Class<?>) o;
            return clazz.getName();
        } else {
            return o.getClass().getName();
        }
    }

    /**
     * 对象转换为字符串
     *
     * @param o
     * @return
     */
    private String toJSONString(Object o) {
        String value;
        if (o == null) {
            return null;
        } else if (o instanceof String) {
            value = (String) o;
        } else if (o instanceof Date) {
            value = DateUtil.format((Date) o, DateUtil.STANDARD_FORMAT);
        } else {
            value = JSON.toJSONString(o);
        }
        return value;
    }

    /**
     * 字符串转换为对象
     *
     * @param text
     * @param clazz
     * @param <T>
     * @return
     */
    private <T> T parseObject(String text, Class<T> clazz) {
        String clazzName = clazz.getSimpleName();
        if (StringUtils.isBlank(text)) {
            return null;
        } else if (Long.class.getSimpleName().equals(clazzName)) {
            return (T) Long.valueOf(text);
        } else if (Integer.class.getSimpleName().equals(clazzName)) {
            return (T) Integer.valueOf(text);
        } else if (String.class.getSimpleName().equals(clazzName)) {
            return (T) text;
        } else if (Double.class.getSimpleName().equals(clazzName)) {
            return (T) (Double.valueOf(text));
        } else if (Date.class.getSimpleName().equals(clazzName)) {
            return (T) DateUtil.format(text, DateUtil.STANDARD_FORMAT);
        } else {
            return JSON.parseObject(text, clazz);
        }
    }

    /**
     * 获取redis耗时的开始时间
     *
     * @return
     */
    private long logRedisConsumeStartTime() {
        if (RedisConfig.consumeTimeSwitcher) {
            return System.currentTimeMillis();
        }
        return 0L;
    }

    /**
     * 记录redis耗时
     *
     * @param method    调用方法
     * @param key       缓存key
     * @param startTime 记录开始时间
     * @param expires   缓存过期时间
     */
    private void logRedisCallConsumeTime(String method, String key, long startTime, long expires) {
        if (RedisConfig.consumeTimeSwitcher) {
            String expiresTimeStr = (expires == -1 ? "0" : String.valueOf(expires));

            long spendTime = System.currentTimeMillis() - startTime;
            if (spendTime > RedisConfig.consumeTimeThreshold) {
                LogHelper.getInstatnce("redisConsumeTimeLog").write(
                        filterMethodName(method)
                                + "," + key
                                + "," + spendTime
                                + "," + expiresTimeStr);
            }
        }
    }

    // helper method
    private static Map<String, String> methodNameMap = new HashMap<>();

    private String filterMethodName(String methodName) {
        String methodNameFiltered = methodNameMap.get(methodName);
        if (methodNameFiltered == null) {
            methodNameFiltered = methodName.replaceAll(",", "|");
            methodNameMap.put(methodName, methodNameFiltered);
        }
        return methodNameFiltered;
    }
}
